lib/xlat_tables: Add support for ARMv8.4-TTST
authorSathees Balya <[email protected]>
Fri, 25 Jan 2019 11:36:01 +0000 (11:36 +0000)
committerSathees Balya <[email protected]>
Wed, 30 Jan 2019 11:17:38 +0000 (11:17 +0000)
ARMv8.4-TTST (Small Translation tables) relaxes the lower limit on the
size of translation tables by increasing the maximum permitted value
of the T1SZ and T0SZ fields in TCR_EL1, TCR_EL2, TCR_EL3, VTCR_EL2 and
VSTCR_EL2.

This feature is supported in AArch64 state only.

This patch adds support for this feature to both versions of the
translation tables library. It also removes the static build time
checks for virtual address space size checks to runtime assertions.

Change-Id: I4e8cebc197ec1c2092dc7d307486616786e6c093
Signed-off-by: Sathees Balya <[email protected]>
13 files changed:
include/arch/aarch64/arch.h
include/arch/aarch64/arch_features.h
include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
include/lib/xlat_tables/xlat_tables_arch.h
include/lib/xlat_tables/xlat_tables_v2_helpers.h
lib/xlat_tables/aarch32/xlat_tables.c
lib/xlat_tables/aarch64/xlat_tables.c
lib/xlat_tables/xlat_tables_private.h
lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
lib/xlat_tables_v2/xlat_tables_core.c
lib/xlat_tables_v2/xlat_tables_private.h

index 9e2bfface17a2698534dc92b989953497f567435..76c3e277bd095456e8bdb845883a28df20547336 100644 (file)
 
 /* ID_AA64MMFR2_EL1 definitions */
 #define ID_AA64MMFR2_EL1               S3_0_C0_C7_2
+
+#define ID_AA64MMFR2_EL1_ST_SHIFT      U(28)
+#define ID_AA64MMFR2_EL1_ST_MASK       ULL(0xf)
+
 #define ID_AA64MMFR2_EL1_CNP_SHIFT     U(0)
 #define ID_AA64MMFR2_EL1_CNP_MASK      ULL(0xf)
 
 
 #define TCR_TxSZ_MIN           ULL(16)
 #define TCR_TxSZ_MAX           ULL(39)
+#define TCR_TxSZ_MAX_TTST      ULL(48)
 
 /* (internal) physical address size bits in EL3/EL1 */
 #define TCR_PS_BITS_4GB                ULL(0x0)
index 2b09ba07f9a3e04aaa8f74bf02b107f0157382b6..9bf43bf85ab492a8e452b4738b9e2c8e13c78946 100644 (file)
@@ -17,4 +17,10 @@ static inline bool is_armv8_2_ttcnp_present(void)
                ID_AA64MMFR2_EL1_CNP_MASK) != 0U;
 }
 
+static inline bool is_armv8_4_ttst_present(void)
+{
+       return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
+               ID_AA64MMFR2_EL1_ST_MASK) == 1U;
+}
+
 #endif /* ARCH_FEATURES_H */
index a333d1e4e3a3462100ae5493823aa9b276fcc8b8..30eb5e9ec4991abe318a8aeb7a10eb9fb967c2d4 100644 (file)
@@ -63,8 +63,7 @@
  * is 1.
  *
  * Note that this macro assumes that the given virtual address space size is
- * valid. Therefore, the caller is expected to check it is the case using the
- * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ * valid.
  */
 #define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz)                 \
        (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) ?  \
index cc5624c91e3a95eeee5d6d4d7793d4578e8792ad..3014c8fea44d21953375ecf48c9508ca6c114915 100644 (file)
@@ -43,14 +43,22 @@ unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr);
  * state.
  *
  * TCR.TxSZ is calculated as 64 minus the width of said address space.
- * The value of TCR.TxSZ must be in the range 16 to 39 [1], which means that
- * the virtual address space width must be in the range 48 to 25 bits.
+ * The value of TCR.TxSZ must be in the range 16 to 39 [1] or 48 [2],
+ * depending on Small Translation Table Support which means that
+ * the virtual address space width must be in the range 48 to 25 or 16 bits.
  *
  * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
  * information:
  * Page 1730: 'Input address size', 'For all translation stages'.
+ * [2] See section 12.2.55 in the ARMv8-A Architecture Reference Manual
+ * (DDI 0487D.a)
  */
+/* Maximum value of TCR_ELx.T(0,1)SZ is 39 */
 #define MIN_VIRT_ADDR_SPACE_SIZE       (ULL(1) << (U(64) - TCR_TxSZ_MAX))
+
+/* Maximum value of TCR_ELx.T(0,1)SZ is 48 */
+#define MIN_VIRT_ADDR_SPACE_SIZE_TTST  \
+                               (ULL(1) << (U(64) - TCR_TxSZ_MAX_TTST))
 #define MAX_VIRT_ADDR_SPACE_SIZE       (ULL(1) << (U(64) - TCR_TxSZ_MIN))
 
 /*
@@ -58,9 +66,13 @@ unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr);
  * virtual address space size. For a 4 KB page size,
  * - level 0 supports virtual address spaces of widths 48 to 40 bits;
  * - level 1 from 39 to 31;
- * - level 2 from 30 to 25.
+ * - level 2 from 30 to 22.
+ * - level 3 from 21 to 16.
  *
- * Wider or narrower address spaces are not supported. As a result, level 3
+ * Small Translation Table (Armv8.4-TTST) support allows the starting level
+ * of the translation table from 3 for 4KB granularity. See section 12.2.55 in
+ * the ARMv8-A Architecture Reference Manual (DDI 0487D.a). In Armv8.3 and below
+ * wider or narrower address spaces are not supported. As a result, level 3
  * cannot be used as initial lookup level with 4 KB granularity. See section
  * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
  * information.
@@ -71,13 +83,14 @@ unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr);
  * is 1.
  *
  * Note that this macro assumes that the given virtual address space size is
- * valid. Therefore, the caller is expected to check it is the case using the
- * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ * valid.
  */
 #define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz)         \
        (((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT))    \
        ? 0U                                                            \
-        : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \
-        ? 1U : 2U))
+       : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT))  \
+       ? 1U                                                            \
+       : (((_virt_addr_space_sz) > (ULL(1) << L2_XLAT_ADDRESS_SHIFT))  \
+       ? 2U : 3U)))
 
 #endif /* XLAT_TABLES_AARCH64_H */
index 251b0206ac050f6d6d591307cf300a2139d29b6e..723753403be174d4e30e7d271a83d033c8a336c8 100644 (file)
 #include "aarch64/xlat_tables_aarch64.h"
 #endif
 
-/*
- * Evaluates to 1 if the given virtual address space size is valid, or 0 if it's
- * not.
- *
- * A valid size is one that is a power of 2 and is within the architectural
- * limits. Not that these limits are different for AArch32 and AArch64.
- */
-#define CHECK_VIRT_ADDR_SPACE_SIZE(size)                       \
-       (((unsigned long long)(size) >= MIN_VIRT_ADDR_SPACE_SIZE) &&    \
-       ((unsigned long long)(size) <= MAX_VIRT_ADDR_SPACE_SIZE) &&     \
-       IS_POWER_OF_TWO(size))
-
 /*
  * Evaluates to 1 if the given physical address space size is a power of 2,
  * or 0 if it's not.
index ce5cf820a0e5132c06d639d47fd4bc0b05dc0a28..6a1be3258ce00e48002368f9527a5cf69ad78554 100644 (file)
@@ -125,9 +125,6 @@ struct xlat_ctx {
 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,                \
                        _xlat_tables_count, _virt_addr_space_size,      \
                        _phy_addr_space_size, _xlat_regime, _section_name)\
-       CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size),      \
-               assert_invalid_virtual_addr_space_size_for_##_ctx_name);\
-                                                                       \
        CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),        \
                assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
                                                                        \
index 468a9e7dd695140608cf5f6d8c7db91212ef4dec..4b01b9b7ab171f5ebdecfeabe1442ee56c19e85c 100644 (file)
@@ -55,6 +55,11 @@ void init_xlat_tables(void)
 {
        unsigned long long max_pa;
        uintptr_t max_va;
+
+       assert(PLAT_VIRT_ADDR_SPACE_SIZE >= MIN_VIRT_ADDR_SPACE_SIZE);
+       assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE);
+       assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE));
+
        print_mmap();
        init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
                                                &max_va, &max_pa);
index 71f491a2192183b86aabebd0dc8524d691781291..e64fd3ef73218cbfd57000365dace96116f100b8 100644 (file)
@@ -10,7 +10,7 @@
 #include <platform_def.h>
 
 #include <arch.h>
-#include <arch_helpers.h>
+#include <arch_features.h>
 #include <common/bl_common.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables.h>
@@ -79,6 +79,21 @@ static unsigned long long get_max_supported_pa(void)
 
        return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
 }
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+static uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+       uintptr_t ret;
+
+       if (is_armv8_4_ttst_present())
+               ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+       else
+               ret = MIN_VIRT_ADDR_SPACE_SIZE;
+
+       return ret;
+}
 #endif /* ENABLE_ASSERTIONS */
 
 unsigned int xlat_arch_current_el(void)
@@ -104,6 +119,12 @@ void init_xlat_tables(void)
 {
        unsigned long long max_pa;
        uintptr_t max_va;
+
+       assert(PLAT_VIRT_ADDR_SPACE_SIZE >=
+               (xlat_get_min_virt_addr_space_size() - 1U));
+       assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE);
+       assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE));
+
        print_mmap();
        init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE,
                           &max_va, &max_pa);
index 4390f34ead7e390170caf92bd74f2efc9f6b77bd..82bc70cd013f031c614b4bee3d452b7b127cb146 100644 (file)
@@ -16,9 +16,6 @@
 #error xlat tables v2 must be used with HW_ASSISTED_COHERENCY
 #endif
 
-CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(PLAT_VIRT_ADDR_SPACE_SIZE),
-       assert_valid_virt_addr_space_size);
-
 CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(PLAT_PHY_ADDR_SPACE_SIZE),
        assert_valid_phy_addr_space_size);
 
index 913c86d39c1e18945b8078f9a1feed29df44a5ff..b69c6702ba9d10c6601db0d4f776496b7b7afac2 100644 (file)
@@ -45,6 +45,14 @@ unsigned long long xlat_arch_get_max_supported_pa(void)
        /* Physical address space size for long descriptor format. */
        return (1ULL << 40) - 1ULL;
 }
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+       return MIN_VIRT_ADDR_SPACE_SIZE;
+}
 #endif /* ENABLE_ASSERTIONS*/
 
 bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
@@ -193,7 +201,12 @@ void setup_mmu_cfg(uint64_t *params, unsigned int flags,
        if (max_va != UINT32_MAX) {
                uintptr_t virtual_addr_space_size = max_va + 1U;
 
-               assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+               assert(virtual_addr_space_size >=
+                       xlat_get_min_virt_addr_space_size());
+               assert(virtual_addr_space_size <=
+                       MAX_VIRT_ADDR_SPACE_SIZE);
+               assert(IS_POWER_OF_TWO(virtual_addr_space_size));
+
                /*
                 * __builtin_ctzll(0) is undefined but here we are guaranteed
                 * that virtual_addr_space_size is in the range [1, UINT32_MAX].
index 228f751471aa279410b8bd0697084931b9d9b41d..e7593dde76581799be3c0c3d6f8cf8c68a855fe5 100644 (file)
@@ -101,6 +101,21 @@ unsigned long long xlat_arch_get_max_supported_pa(void)
 
        return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL;
 }
+
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+       uintptr_t ret;
+
+       if (is_armv8_4_ttst_present())
+               ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+       else
+               ret = MIN_VIRT_ADDR_SPACE_SIZE;
+
+       return ret;
+}
 #endif /* ENABLE_ASSERTIONS*/
 
 bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
@@ -221,7 +236,11 @@ void setup_mmu_cfg(uint64_t *params, unsigned int flags,
        assert(max_va < ((uint64_t)UINTPTR_MAX));
 
        virtual_addr_space_size = (uintptr_t)max_va + 1U;
-       assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+
+       assert(virtual_addr_space_size >=
+               xlat_get_min_virt_addr_space_size());
+       assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE);
+       assert(IS_POWER_OF_TWO(virtual_addr_space_size));
 
        /*
         * __builtin_ctzll(0) is undefined but here we are guaranteed that
index c49554f1f12dc0eedb31e8e51d37b077fa50ca17..4820b4f8052f2936e27c074c62b1213a0e7894ab 100644 (file)
@@ -1146,6 +1146,11 @@ void __init init_xlat_tables_ctx(xlat_ctx_t *ctx)
 
        mmap_region_t *mm = ctx->mmap;
 
+       assert(ctx->va_max_address >=
+               (xlat_get_min_virt_addr_space_size() - 1U));
+       assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U));
+       assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U));
+
        xlat_mmap_print(mm);
 
        /* All tables must be zeroed before mapping any region. */
index fc709554bb0bf76462d5ff7e26954171187e542c..70ef395235d004b85e05d8de3753326c5ce08d78 100644 (file)
@@ -102,4 +102,9 @@ bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx);
 /* Returns true if the data cache is enabled at the current EL. */
 bool is_dcache_enabled(void);
 
+/*
+ * Returns minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void);
+
 #endif /* XLAT_TABLES_PRIVATE_H */